#pragma once
#include "requestor.hpp"

namespace rpc
{
    namespace client
    {
        //向用户提供rpc调用的模块
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallback = std::function<void(const Json::Value &)>;
            RpcCaller(const Requestor::ptr &requestor) : _requestor(requestor) {}
            //同步调用
            bool call(const BaseConnection::ptr &conn, const std::string &method, const Json::Value &params, Json::Value &result)
            {
                LOG(DEBUG,"开始同步rpc调用...");
                
                auto req_msg = MessageFactory::create<RpcRequest>();//创建Rpc请求对象
                req_msg->setId(UUID::uuid());//用UUID设置消息Id
                req_msg->setMType(MType::REQ_RPC);//设置消息类型
                req_msg->setMethod(method);//设置body的方法
                req_msg->setParams(params);//设置body的方法的参数
                BaseMessage::ptr rsp_msg;
                // std::dynamic_pointer_cast<BaseMessage>(req_msg)   //dynamic_cast用于裸指针和引用等动态类型的转型，而dynamic_pointer_cast主要用于智能指针的转型。
                bool ret = _requestor->send(conn, req_msg, rsp_msg);//同步发送消息
                if (ret == false) {
                    LOG(DEBUG,"同步Rpc请求失败");
                    return false;
                }
                LOG(INFO,"收到响应，进行解析，获取结果!");
                
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);//向下类型转换
                if (!rpc_rsp_msg) {
                    LOG(DEBUG,"rpc响应,向下类型转换失败");
                    return false;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK) {
                    LOG(DEBUG,"rpc请求出错:%s", errReason(rpc_rsp_msg->rcode()).c_str());
                    return false;
                }
                result = rpc_rsp_msg->result();
                LOG(INFO,"结果设置完毕！");
                return true;
            }

            //requestor中的处理是针对BaseMessage进行处理的
            //rpc_caller中针对结果的处理是RpcResponse中的result进行处理的
            //异步调用
            bool call(const BaseConnection::ptr & conn,const std::string & method,const Json::Value & params,JsonAsyncResponse & result)
            {
                //向服务器设置回调函数,回调函数会传入一个promise对象,然后在回调函数中对promise设置数据
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallback cb = std::bind(&RpcCaller::Callback,this,json_promise,std::placeholders::_1);//json_promise使用智能指针,避免出了作用域销毁
                // bool ret  = _requestor->send(conn,std::dynamic_pointer_cast<BaseMessage>(req_msg),cb);
                bool ret  = _requestor->send(conn,req_msg,cb);
                if(ret == false)
                {
                    LOG(ERROR,"异步rpc请求失败");
                    return false;
                }
                return true;
            }

            //回调函数调用
            bool call(const BaseConnection::ptr & conn,const std::string & method,const Json::Value & params,const JsonResponseCallback & cb)
            {
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UUID::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                Requestor::RequestCallback req_cb = std::bind(&RpcCaller::Callback1,this,cb,std::placeholders::_1);
                bool ret = _requestor->send(conn,req_msg,req_cb);
                if(ret == false)
                {
                    LOG(ERROR,"回调rpc请求失败");
                    return false;
                }
                return true;
            }

        private:
            void Callback1(const JsonResponseCallback &cb, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    LOG(ERROR, "rpc响应,向下类型转换失败");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    LOG(ERROR, "rpc回调请求出错:%s", errReason(rpc_rsp_msg->rcode()));
                    return;
                }
                cb(rpc_rsp_msg->result());
            }

            void Callback(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr &msg)
            {
                auto rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    LOG(ERROR, "rpc响应,向下类型转换失败");
                    return;
                }
                if (rpc_rsp_msg->rcode() != RCode::RCODE_OK)
                {
                    LOG(ERROR, "rpc异步请求出错,%s", errReason(rpc_rsp_msg->rcode()));
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }
        private:
            Requestor::ptr _requestor;//通过Requestor对象向服务端发送消息
        };
    }
}

